Working with Formatting and Internationalization Tags in JSP
Course: Advanced Java Training
Topic: Working with Formatting and Internationalization Tags
Course Link: Advanced Java Training Course
Demo Link: Register for a Course Demo
Website: JustAcademy Official Website
1. Introduction
Formatting and internationalization are important features of JavaServer Pages (JSP) that help web applications display dates, times, numbers, currencies, and messages in a user-friendly way. Applications used by people from different countries must account for differences in languages, date formats, number separators, currencies, and regional conventions.
JSTL (JSP Standard Tag Library) provides formatting and internationalization tags that reduce the need for Java scriptlets in JSP pages. These tags help developers format values, parse user input, choose a locale, and display localized messages from resource bundles.
The formatting and internationalization tags are commonly accessed through the fmt prefix. The exact tag library URI and dependency configuration depend on the JSTL or Jakarta Tags version used by the application.
2. Learning Objectives
- Understand internationalization (i18n) and localization (l10n).
- Learn the purpose of JSTL formatting and internationalization tags.
- Configure the formatting tag library in a JSP page.
- Format dates, times, numbers, percentages, and currencies.
- Parse formatted dates and numeric values.
- Set the locale used to display information.
- Load localized messages using resource bundles.
- Use message parameters and handle missing translations.
- Apply best practices for multilingual JSP applications.
3. What Is Internationalization?
Internationalization, abbreviated as i18n, is the process of designing an application so it can support multiple languages and regional conventions without requiring major code changes for every language.
For example, an online shopping application may display a product price, date, and welcome message differently depending on the user's locale.
| Information |
Example |
Regional variation |
| Date |
10/23/2026 |
23/10/2026 |
| Number |
1,234.56 |
1.234,56 |
| Currency |
$1,234.56 |
€1.234,56 |
| Message |
Welcome |
Bienvenido |
These examples illustrate common differences. Actual output depends on the locale, formatting style, currency configuration, and available locale data.
4. What Is Localization?
Localization, abbreviated as l10n, is the process of adapting an application to a particular language or region. It includes translating text and presenting dates, numbers, currencies, and other values according to local conventions.
Internationalization prepares an application to support multiple locales, while localization provides the translations and regional settings for a specific locale.
Example
A website can use one JSP page for its welcome message while storing English, French, and Spanish translations in separate resource bundle files. The page selects the appropriate message based on the active locale rather than maintaining a separate JSP page for every language.
5. Introduction to JSTL Formatting Tags
The JSTL formatting library contains tags for locale selection, resource bundles, message retrieval, number formatting, and date formatting. The tags are usually accessed through the fmt prefix.
| Tag |
Purpose |
fmt:setLocale |
Sets the locale for formatting and message processing. |
fmt:requestEncoding |
Sets the character encoding used to decode request parameters. |
fmt:setBundle |
Loads a resource bundle and stores it in a scoped variable. |
fmt:bundle |
Provides a resource bundle for nested message tags. |
fmt:message |
Displays a localized message from a resource bundle. |
fmt:param |
Supplies a parameter to a localized message. |
fmt:formatNumber |
Formats numbers, currencies, and percentages. |
fmt:parseNumber |
Parses a locale-formatted string into a number. |
fmt:formatDate |
Formats date and time values. |
fmt:parseDate |
Parses a date string into a date value. |
fmt:timeZone |
Specifies a time zone for nested formatting operations. |
fmt:setTimeZone |
Sets a time zone in a scoped variable for formatting operations. |
Exact tag availability and accepted attributes can vary by JSTL/Jakarta Tags version. Verify the library documentation for the version used by the application.
6. Configuring the Formatting Tag Library
Before using formatting tags, ensure that the correct JSTL implementation is included in the web application's dependencies and deployed to a compatible servlet container.
For a Jakarta Tags 3.0 application, the formatting tag library is commonly declared as follows:
<%@ taglib prefix="fmt" uri="jakarta.tags.fmt" %>
Older JSTL 1.2 applications commonly use this Java EE tag library URI:
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
Important: Do not mix incompatible Jakarta and older Java EE dependencies or tag library declarations. Use the URI and dependency versions supported by the target application server.
7. Setting the Locale with fmt:setLocale
A locale identifies a language and, optionally, a country or regional variant. It influences how dates, numbers, and localized messages are displayed.
The fmt:setLocale tag sets the locale for subsequent JSTL formatting operations. A locale can be represented by values such as en_US, en_GB, or fr_FR, subject to the tag library's supported locale syntax.
Example
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="fmt" uri="jakarta.tags.fmt" %>
<fmt:setLocale value="en_GB" />
<fmt:formatNumber value="12345.67" type="number" />
The number is formatted according to the selected locale's conventions. Locale selection should follow an application policy, such as a validated user preference or a supported language setting.
8. Formatting Numbers with fmt:formatNumber
The fmt:formatNumber tag converts a numeric value into a locale-aware display string. It can display a standard number, currency, or percentage and can optionally control decimal places and patterns.
8.1 Formatting a Standard Number
<fmt:formatNumber value="1234567.891" type="number" />
The output may contain locale-specific grouping separators and decimal symbols. For example, one locale may use commas for grouping and a period for decimals, while another uses different separators.
8.2 Controlling Decimal Places
<fmt:formatNumber
value="1234.5678"
type="number"
minFractionDigits="2"
maxFractionDigits="2" />
This example requests two fractional digits. Formatting rounds the displayed value as necessary; it does not change the underlying numeric value.
8.3 Formatting Currency
<fmt:setLocale value="en_US" />
<fmt:formatNumber value="2499.5" type="currency" />
The tag formats the value as currency using locale conventions. For financial applications, do not assume that the locale alone represents the business currency. Select and validate the currency according to the application's requirements.
8.4 Formatting Percentages
<fmt:formatNumber value="0.875" type="percent" />
A decimal fraction such as 0.875 is displayed as a percentage, commonly as 88% depending on rounding and formatting rules. If the application stores percentages as whole numbers, convert them to the expected fractional representation before formatting.
8.5 Using a Custom Pattern
<fmt:formatNumber
value="12345.678"
pattern="#,##0.00" />
A pattern gives more direct control over numeric presentation. The symbols are formatting instructions rather than literal text. Test patterns with the application's selected locale.
9. Important Attributes of fmt:formatNumber
| Attribute |
Description |
value |
The numeric value to format. |
type |
Specifies number, currency, or percent formatting. |
pattern |
Provides a custom numeric pattern. |
currencyCode |
Specifies a currency code when supported and appropriate. |
currencySymbol |
Specifies a currency symbol for display where supported. |
minFractionDigits |
Sets the minimum number of fractional digits. |
maxFractionDigits |
Sets the maximum number of fractional digits. |
minIntegerDigits |
Sets the minimum number of integer digits. |
groupingUsed |
Controls whether grouping separators are used. |
var |
Stores the formatted string in a variable instead of directly displaying it. |
scope |
Specifies the scope for a variable when var is used. |
```html
10. Parsing Numbers with fmt:parseNumber
The fmt:parseNumber tag converts a string containing a formatted number into a numeric value. It is useful when processing data entered or supplied in a known locale-specific format.
10.1 Basic Number Parsing
<%@ taglib prefix="fmt" uri="jakarta.tags.fmt" %>
<fmt:setLocale value="en_US" />
<fmt:parseNumber value="1,234.50" var="amount" />
<p>Parsed amount: ${amount}</p>
The input must match the expected locale and formatting rules. Parsing arbitrary user input without validation can produce errors or incorrect values.
10.2 Parsing a Percentage
<fmt:setLocale value="en_US" />
<fmt:parseNumber value="75%" type="percent" var="ratio" />
<p>Parsed ratio: ${ratio}</p>
When parsing a percentage, the result is generally represented as a fraction rather than a whole-number percentage. Verify the expected result and data type in the application.
10.3 Important Attributes
| Attribute |
Description |
value |
The string containing the number to parse. |
type |
Specifies number, currency, or percent parsing. |
pattern |
Defines the expected numeric pattern. |
parseLocale |
Specifies the locale used to parse the input. |
integerOnly |
Controls whether parsing is restricted to the integer portion. |
var |
Stores the parsed value in a scoped variable. |
scope |
Defines the scope of the result variable. |
11. Formatting Dates and Times with fmt:formatDate
The fmt:formatDate tag formats supported date/time values using locale-sensitive rules. It can display a date, a time, or both.
11.1 Basic Date Formatting
<%@ page import="java.util.Date" %>
<%@ taglib prefix="fmt" uri="jakarta.tags.fmt" %>
<jsp:useBean id="today" class="java.util.Date" />
<fmt:formatDate value="${today}" type="date" dateStyle="long" />
The date style determines the level of detail used in the output. The rendered date depends on the active locale.
11.2 Formatting Time
<fmt:formatDate value="${today}" type="time" timeStyle="short" />
This displays the time in a locale-appropriate short format. Whether the output includes seconds or a 12-hour or 24-hour clock depends on the locale and style.
11.3 Formatting Date and Time Together
<fmt:formatDate
value="${today}"
type="both"
dateStyle="medium"
timeStyle="short" />
Use a combined date/time display when the user needs to see both the calendar date and the time of an event.
11.4 Formatting with a Custom Pattern
<fmt:formatDate
value="${today}"
pattern="dd MMM yyyy HH:mm" />
The pattern controls the displayed date and time components. In Java date patterns, uppercase and lowercase letters may have different meanings. For example, MM represents a month, while mm represents minutes.
12. Parsing Dates with fmt:parseDate
The fmt:parseDate tag converts a formatted date string into a date value. The string must match the selected locale and, where specified, the expected date pattern.
Example
<%@ taglib prefix="fmt" uri="jakarta.tags.fmt" %>
<fmt:setLocale value="en_GB" />
<fmt:parseDate
value="23/10/2026"
pattern="dd/MM/yyyy"
var="parsedDate" />
<fmt:formatDate value="${parsedDate}" dateStyle="long" />
Using a pattern makes the expected input format explicit. Avoid relying on ambiguous values such as 04/05/2026, which may represent different dates in different regions.
Important Attributes
| Attribute |
Purpose |
value |
The date string to parse. |
type |
Indicates whether the input contains a date, time, or both. |
dateStyle |
Specifies the date parsing style. |
timeStyle |
Specifies the time parsing style. |
pattern |
Defines the expected date/time pattern. |
timeZone |
Specifies the time zone for parsing. |
parseLocale |
Specifies the locale used to interpret the input. |
var |
Stores the parsed date in a variable. |
13. Working with Time Zones
A time zone determines how a timestamp is represented as local clock time. Applications that support users in multiple regions should decide whether to display times in the user's time zone, the event's time zone, or a standard time zone such as UTC.
The fmt:timeZone tag establishes a time zone for nested formatting and parsing tags. The fmt:setTimeZone tag can set a time zone in a scoped variable for subsequent formatting operations.
Example
<fmt:timeZone value="UTC">
<fmt:formatDate
value="${today}"
type="both"
dateStyle="medium"
timeStyle="short" />
</fmt:timeZone>
Use valid time zone identifiers supported by the Java runtime. Be careful when converting event times because daylight-saving rules and regional changes can affect the displayed result.
Difference Between the Time-Zone Tags
| Tag |
Usage |
fmt:timeZone |
Applies a time zone to nested date formatting or parsing operations. |
fmt:setTimeZone |
Stores a time zone in the JSTL formatting configuration for subsequent operations. |
14. Understanding Resource Bundles
A resource bundle stores messages and labels separately from JSP presentation code. This allows the same JSP page to display text in multiple languages without duplicating the page for every language.
Common resource bundle files include:
messages.properties — default messages.
messages_fr.properties — French messages.
messages_es.properties — Spanish messages.
messages_hi.properties — Hindi messages.
Each file contains key-value pairs. The keys remain consistent across languages, while the values contain the translated text.
Example: Default Resource Bundle
messages.properties
page.title=Welcome Page
welcome.message=Welcome to our application!
button.submit=Submit
product.label=Product Price
user.greeting=Hello, {0}!
Example: French Resource Bundle
messages_fr.properties
page.title=Page de bienvenue
welcome.message=Bienvenue dans notre application !
button.submit=Envoyer
product.label=Prix du produit
user.greeting=Bonjour, {0} !
Resource bundles should be placed in a location accessible to the application's class loader. Follow the encoding and escaping conventions supported by the Java version and resource bundle mechanism in use, particularly for non-ASCII characters.
15. Using fmt:setBundle
The fmt:setBundle tag loads a resource bundle and stores it in a variable so its messages can be accessed by formatting tags.
Example
<%@ taglib prefix="fmt" uri="jakarta.tags.fmt" %>
<fmt:setLocale value="en" />
<fmt:setBundle basename="messages" var="msg" />
<h1><fmt:message key="page.title" bundle="${msg}" /></h1>
<p><fmt:message key="welcome.message" bundle="${msg}" /></p>
The basename identifies the resource bundle without the locale suffix or file extension. For example, messages refers to the default messages.properties file and locale-specific variants.
16. Displaying Localized Messages with fmt:message
The fmt:message tag retrieves a message by key from the active or specified resource bundle. This keeps translated content out of the JSP's structural markup.
Example
<fmt:setBundle basename="messages" var="msg" />
<h1><fmt:message key="page.title" bundle="${msg}" /></h1>
<p><fmt:message key="welcome.message" bundle="${msg}" /></p>
When a matching resource bundle is available for the selected locale, the localized value is used. Java's resource bundle lookup can fall back to a more general locale or the default bundle when a locale-specific translation is unavailable.
17. Passing Dynamic Values with fmt:param
Localized messages often need dynamic values such as a user's name, order number, or item count. The fmt:param tag supplies values for placeholders in a message.
Resource Bundle
user.greeting=Hello, {0}!
order.status=Order {0} has {1} items.
JSP Example
<fmt:setBundle basename="messages" var="msg" />
<fmt:message key="user.greeting" bundle="${msg}">
<fmt:param value="${userName}" />
</fmt:message>
<fmt:message key="order.status" bundle="${msg}">
<fmt:param value="${orderNumber}" />
<fmt:param value="${itemCount}" />
</fmt:message>
Translators may need to change sentence structure between languages. Use message placeholders instead of assembling translated sentences from separate fragments.
18. Using fmt:bundle
The fmt:bundle tag establishes a localization context for tags nested inside its body. It is useful when several messages on a page share the same resource bundle.
Example
<fmt:bundle basename="messages">
<h1><fmt:message key="page.title" /></h1>
<p><fmt:message key="welcome.message" /></p>
<button type="submit">
<fmt:message key="button.submit" />
</button>
</fmt:bundle>
Messages inside the bundle use its localization context unless a more specific context is supplied. This reduces repeated bundle configuration in the JSP.
19. Setting Request Character Encoding
Internationalized applications must handle characters from different writing systems correctly. The fmt:requestEncoding tag sets the character encoding used to decode request parameters.
<%@ taglib prefix="fmt" uri="jakarta.tags.fmt" %>
<fmt:requestEncoding value="UTF-8" />
Set request encoding before reading request parameters. In practice, request encoding is often configured in a servlet filter or application framework so it is applied consistently. Setting the page response encoding is a separate concern; a JSP may use a page directive such as contentType="text/html; charset=UTF-8".
20. Choosing a Locale Dynamically
A multilingual application should select the locale using a consistent policy. Common options include the user's saved language preference, a validated language choice, or the browser's accepted-language information.
The following example illustrates selecting a locale from an application-controlled setting. The variable userLocale should contain a validated locale value supplied by the controller or another trusted application component.
<%@ taglib prefix="fmt" uri="jakarta.tags.fmt" %>
<fmt:setLocale value="${userLocale}" />
<fmt:setBundle basename="messages" var="msg" />
<h1><fmt:message key="page.title" bundle="${msg}" /></h1>
Do not accept arbitrary locale values without validation. Define the locales supported by the application and use a default locale when the requested locale is unsupported.
21. Complete Example: Localized Product Summary
The following example combines locale selection, resource bundles, currency formatting, and date formatting in a JSP page.
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page import="java.util.Date" %>
<%@ taglib prefix="fmt" uri="jakarta.tags.fmt" %>
<fmt:setLocale value="en_US" />
<fmt:setBundle basename="messages" var="msg" />
<jsp:useBean id="today" class="java.util.Date" />
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title><fmt:message key="page.title" bundle="${msg}" /></title>
</head>
<body>
<h1><fmt:message key="welcome.message" bundle="${msg}" /></h1>
<p><fmt:message key="product.label" bundle="${msg}" />:
<fmt:formatNumber value="1299.99" type="currency" />
</p>
<p>Report generated:
<fmt:formatDate value="${today}" type="both"
dateStyle="medium" timeStyle="short" />
</p>
</body>
</html>
In a production application, the locale should normally be chosen from a validated user preference, session setting, or request-level locale policy rather than hard-coded into every JSP.
22. Formatting Tags vs. Internationalization Tags
| Aspect |
Formatting |
Internationalization |
| Main purpose |
Present or parse numbers, dates, times, and currencies. |
Display messages and text appropriate to a language or region. |
| Common tags |
fmt:formatNumber, fmt:formatDate, fmt:parseNumber, fmt:parseDate |
fmt:setLocale, fmt:setBundle, fmt:bundle, fmt:message |
| Typical input |
A number, date, time, or formatted string. |
A locale, resource bundle, message key, or parameter. |
| Typical output |
A locale-aware string or parsed value. |
A translated message or configured localization context. |
| Example |
Displaying a price with currency formatting. |
Displaying a translated checkout heading. |
23. Common Errors and Troubleshooting
| Problem |
Possible Cause |
Solution |
| Formatting tag is not recognized |
Incorrect tag library URI or missing JSTL dependency. |
Verify the JSTL version, dependency, server compatibility, and taglib declaration. |
| Message key is missing |
The key does not exist in the selected resource bundle. |
Check spelling, bundle basename, file location, and translated property keys. |
| Wrong date appears |
The input pattern does not match the actual date string. |
Use an explicit pattern and validate the input format. |
| Number parsing fails |
The string uses separators from a different locale. |
Set the intended parsing locale and validate the submitted value. |
| Currency symbol is unexpected |
The selected locale does not match the intended business currency. |
Set the appropriate locale and explicitly manage the currency where needed. |
| Time appears shifted |
The configured time zone differs from the expected time zone. |
Choose a consistent time-zone policy and configure it explicitly. |
| Translated characters appear incorrectly |
Incorrect character encoding in the request, response, or properties file. |
Use UTF-8 consistently and verify file encoding and response headers. |
| Locale changes do not affect output |
A localization context or explicit locale overrides the expected setting. |
Check tag nesting, bundle configuration, and the order of locale selection. |
24. Security and Best Practices
- Separate content from presentation: Store translatable text in resource bundles rather than hard-coding messages throughout JSP files.
- Validate locale choices: Support only configured locales and provide a predictable default.
- Validate parsed input: Treat client-supplied numbers and dates as untrusted input. Handle invalid values gracefully.
- Use explicit date patterns when needed: Avoid ambiguous date formats when parsing user input.
- Choose a time-zone policy: Store timestamps consistently and convert them for display according to the application's requirements.
- Handle currencies carefully: Currency formatting changes presentation; it does not perform currency conversion or define financial rounding rules by itself.
- Use consistent character encoding: Configure request decoding and response encoding correctly, preferably using UTF-8.
- Do not concatenate translated fragments: Use parameterized messages so translators can reorder words according to the target language.
- Escape dynamic output: Localized messages that include user-controlled values still require appropriate output escaping. Formatting tags do not automatically make every value safe for HTML.
- Keep business logic outside JSP: Use servlets, controllers, or service classes for validation, currency calculations, and date conversion; use JSP tags primarily for presentation.
- Test all supported locales: Check long translations, special characters, decimal separators, currency display, and date boundaries.
25. Practical Exercise
Create a multilingual JSP page that displays a welcome message, a product price, and the current date.
Requirements
- Create a default
messages.properties file.
- Create at least one translated resource bundle, such as
messages_fr.properties.
- Define message keys for the page title, welcome message, and product label.
- Use
fmt:setLocale to select a supported locale.
- Use
fmt:setBundle and fmt:message to display translated text.
- Use
fmt:formatNumber to format a product price.
- Use
fmt:formatDate to display the current date.
- Test the page with each supported locale and verify the output.
Expected Learning Outcome
After completing the exercise, you should be able to create a JSP page that separates translated messages from presentation markup and formats numeric and date values according to the selected locale.
26. Interview Questions and Answers
Q1. What is internationalization in Java web applications?
Answer: Internationalization is the process of designing an application to support multiple languages and regional conventions without rewriting the application for every locale.
Q2. What is the difference between internationalization and localization?
Answer: Internationalization prepares the application to support multiple locales. Localization adapts its messages and presentation for a particular language or region.
Q3. What is the purpose of the JSTL formatting library?
Answer: It provides tags for locale selection, localized messages, and formatting or parsing numbers, currencies, dates, and times.
Q4. What does fmt:setLocale do?
Answer: It sets the locale used by subsequent JSTL internationalization and formatting operations, subject to the active localization context and configuration.
Q5. What is a resource bundle?
Answer: A resource bundle stores locale-specific values, such as translated messages, separately from application code and JSP markup.
Q6. What is the purpose of fmt:message?
Answer: It retrieves and displays a message from a resource bundle using a message key.
Q7. How do you pass dynamic values into a localized message?
Answer: Use fmt:param inside fmt:message to provide values for placeholders in the message pattern.
Q8. What is the difference between fmt:formatNumber and fmt:parseNumber?
Answer: fmt:formatNumber converts a numeric value into a formatted string. fmt:parseNumber converts a correctly formatted numeric string into a numeric value.
Q9. What is the difference between fmt:formatDate and fmt:parseDate?
Answer: fmt:formatDate presents a date/time value as text. fmt:parseDate parses a date/time string into a date value.
Q10. Why are time zones important?
Answer: The same timestamp can correspond to different local clock times in different regions. A clear time-zone policy helps the application display event times correctly.
Q11. Does currency formatting convert one currency into another?
Answer: No. Currency formatting changes how a value is displayed. Currency conversion requires a separate calculation using an appropriate exchange rate.
Q12. Why should request encoding be configured correctly?
Answer: Correct encoding ensures that submitted text, including non-English characters, is decoded accurately. Request encoding should be set before request parameters are read.
27. Quick Revision Checklist
- Internationalization prepares an application for multiple locales.
- Localization adapts content and formatting for a particular locale.
- The JSTL formatting tag prefix is commonly
fmt.
- Jakarta Tags 3.0 uses the formatting URI
jakarta.tags.fmt.
fmt:setLocale selects the formatting locale.
fmt:setBundle and fmt:bundle provide resource bundle contexts.
fmt:message retrieves localized text.
fmt:param supplies dynamic message values.
fmt:formatNumber formats numbers, currencies, and percentages.
fmt:parseNumber parses locale-formatted numeric strings.
fmt:formatDate formats date and time values.
fmt:parseDate parses date/time strings.
fmt:timeZone and fmt:setTimeZone support time-zone configuration.
- Use consistent character encoding and validate user input.
- Test every supported locale before releasing the application.
28. Conclusion
JSTL formatting and internationalization tags make JSP applications easier to maintain and more accessible to users across languages and regions. Resource bundles keep translated messages separate from page markup, while formatting tags handle locale-sensitive numbers, currencies, dates, and times.
By selecting locales carefully, validating parsed input, managing time zones and currencies correctly, and testing translated content, developers can build reliable multilingual web applications with cleaner JSP pages and less repetitive code.
29. Reference Links